package com.example.java.base.jdk8.lambda;


import org.junit.Test;

import java.util.Comparator;
import java.util.function.Consumer;

/**
 * Lambda1Test:多钟Lambda写法举例
 *
 * @author zhangxiaoxiang
 * @date 2020/10/8
 */
public class Lambda1Test {
    /**
     * 语法格式一：(最简洁性)无参，无返回值
     */
    @Test
    public void test1() {
        Runnable r1 = new Runnable() {
            @Override
            public void run() {
                System.out.println("语法格式一：无参，无返回值");
            }
        };
        r1.run();
        System.out.println("***********************");
        Runnable r2 = () -> {
            System.out.println("语法格式一：无参，无返回值");
        };
        r2.run();
    }

    /**
     * 语法格式二：(消费型)需要一个参数，但是没有返回值。
     */
    @Test
    public void test2() {
        Consumer<String> con = new Consumer<String>() {
            /**
             *
             * @param s 待消费的参数,注意没有返回值
             */
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        con.accept("我是普通写法的入参");
        System.out.println("*******************");
        //如果只有一段简单的实现代码,{}也可以不要  Consumer<String> con1 = (String s) -> {System.out.println(s);};
        // 这里idea会提示Lambda can be replaced with method reference ,可以使用方法写法引用替代,在后面会有示例,这里就保持这种写法
        Consumer<String> con1 = (String s) -> System.out.println(s);
        con1.accept("我是Lambda写法的入参,左边是形参 ->右边是实现,将参数消费");

    }

    /**
     * 语法格式三：(类型推断型)数据类型可以省略，因为可由编译器推断得出，称为“类型推断”,双冒号::写法
     */
    @Test
    public void test3() {
        //idea会建议Lambda can be replaced with method reference
        Consumer<String> con1 = (String s) -> {
            System.out.println(s);
        };
        con1.accept("数据类型可以省略,类型推断的入参");
        System.out.println("*******************");
        //这就是idea建议的Lambda的方法引用method reference 写法
        Consumer<String> con2 = System.out::println;
        con2.accept("::就是方法引用的方式,称为“类型推断”的入参");

    }


    /**
     * 语法格式四：(单参数不要括号)Lambda 若只需要一个参数时，参数的小括号可以省略
     */
    @Test
    public void test4() {
        Consumer<String> con1 = (s) -> {
            System.out.println(s);
        };
        con1.accept("Lambda还可以进一步简化的入参");
        System.out.println("*******************");
        Consumer<String> con2 = System.out::println;
        con2.accept("Lambda 若只需要一个参数时，参数的小括号可以省略的入参");
    }

    /**
     * 语法格式五：(多参数并带返回值)Lambda 需要两个或以上的参数，多条执行语句，并且可以有返回值
     */
    @Test
    public void test5() {
        Comparator<Integer> com1 = new Comparator<Integer>() {
            /**
             * compare方法比较2这个
             * @param o1 待比较的数o1
             * @param o2 待比较的数o2
             * @return o1比o2大返回1小则返回-1,相等返回0
             */
            @Override
            public int compare(Integer o1, Integer o2) {
                System.out.println("两个入参分别是:" + o1 + "  " + o2);
                return o1.compareTo(o2);
            }
        };
        System.out.println("常规写法比较结果(12比21小返回-1): " + com1.compare(12, 21));
        System.out.println("*****************************");
        Comparator<Integer> com2 = (o1, o2) -> {
            System.out.println("两个入参分别是:" + o1 + "  " + o2);
            return o1.compareTo(o2);
        };
        System.out.println("Lambda写法比较结果(12比21小返回-1): " + com2.compare(12, 21));
    }

    /**
     * 语法格式六：当 Lambda 体只有一条语句时，return 与大括号若有，都可以省略
     */
    @Test
    public void test6() {
        Comparator<Integer> com1 = (o1, o2) -> {
            return o1.compareTo(o2);
        };
        System.out.println(com1.compare(12, 21));
        System.out.println("*****************************");
        //Lambda 体只有一条语句时，return 与大括号若有，都可以省略
        Comparator<Integer> com2 = (o1, o2) -> o1.compareTo(o2);
        System.out.println(com2.compare(12, 21));
        //在进一步使用方法引用(推荐)
        Comparator<Integer> com3 = Integer::compareTo;
        System.out.println(com3.compare(12, 21));
    }

}
